package classfile

import (
	"fmt"
	. "jvm/typedef"
)

// *****************************************************************
type Field struct {
	MemberInfo
}

func newFields(reader *BytecodeReader, constantPool ConstantPool) []Field {
	count := reader.readU2()
	fields := make([]Field, count)
	for i := 0; i < int(count); i++ {
		fields[i].constantPool = constantPool
		fields[i].readInfo(reader)
	}
	return fields
}

// *****************************************************************
type Method struct {
	MemberInfo
}

func newMethods(reader *BytecodeReader, constantPool ConstantPool) []Method {
	count := reader.readU2()
	methods := make([]Method, count)
	for i := 0; i < int(count); i++ {
		methods[i].constantPool = constantPool
		methods[i].readInfo(reader)
	}
	return methods
}

func (self *Method) AttributeCode() *AttributeCode {
	for _, attr := range self.attributes {
		if code, ok := attr.(*AttributeCode); ok {
			return code
		}
	}
	return nil
}

// *****************************************************************
// method field通用函数
type MemberInfo struct {
	constantPool    ConstantPool
	accessFlags     U2
	nameIndex       U2
	descriptorIndex U2
	attributes      []Attribute
}

// getter
func (self *MemberInfo) AccessFlags() U2 {
	return self.accessFlags
}
func (self *MemberInfo) GetName() string {
	return self.constantPool.getUtf8(self.nameIndex)
}
func (self *MemberInfo) GetDescriptor() string {
	return self.constantPool.getUtf8(self.descriptorIndex)
}
func (self *MemberInfo) Attributes() []Attribute {
	return self.attributes
}

// print info
func (self *MemberInfo) Print() {
	cp := self.constantPool
	fmt.Printf("access_flags:%d\n", self.accessFlags)
	fmt.Printf("name_index:#%d\t\t%s\n", self.nameIndex, cp.getUtf8(self.nameIndex))
	fmt.Printf("descriptor_index:#%d\t\t%s\n", self.descriptorIndex, cp.getUtf8(self.descriptorIndex))
	fmt.Printf("attributes:#%d\n", len(self.attributes))
	for index, val := range self.attributes {
		fmt.Printf("#%d{", index)
		val.Print()
		fmt.Println("}")
	}
}

func (self *MemberInfo) readInfo(reader *BytecodeReader) {
	self.accessFlags = reader.readU2()
	self.nameIndex = reader.readU2()
	self.descriptorIndex = reader.readU2()
	attributesCount := reader.readU2()
	self.attributes = make([]Attribute, attributesCount)
	for i := 0; i < int(attributesCount); i++ {
		attributeNameIndex := reader.readU2()
		attributeName := self.constantPool.getUtf8(attributeNameIndex)
		self.attributes[i] = newAttribute(attributeName, &self.constantPool)
		self.attributes[i].readInfo(reader)
	}
}
